#include "serveur.h"
#include "ui_serveur.h"
#define NBJOUEUR 2

Serveur::Serveur(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Serveur)
{
    ui->setupUi(this);
    tourcourrant = 0;
    serveur = new QTcpServer(this);
    serveur->setMaxPendingConnections(6);
    if (!serveur->listen(QHostAddress::Any, 33555)) // Démarrage du serveur sur toutes les IP disponibles et sur le port 33555
        ui->etatServeur->setText(QString::fromUtf8("Le serveur n'a pas pu être démarré. Raison :<br />") + serveur->errorString());
    else
    {
        QString ad = QNetworkInterface::allAddresses().at(2).toString();
        ui->etatServeur->setText(QString::fromUtf8("Le serveur a été démarré sur le port <strong>") + QString::number(serveur->serverPort()) + tr("</strong>.<br />Des clients peuvent maintenant se connecter sur l'adresse : <strong>") + ad + tr("</stong>"));
        connect(serveur, SIGNAL(newConnection()), this, SLOT(nouvelleConnexion()));
    }

    tailleMessage = 0;
}

Serveur::~Serveur()
{
    delete ui;
}

void Serveur::nouvelleConnexion()
{
    if(listJoueurs.size() < NBJOUEUR)
        {
            Joueur *nouveauJoueur = new Joueur();
            nouveauJoueur->setSocket(serveur->nextPendingConnection());
            this->listJoueurs.append(nouveauJoueur);


            connect(nouveauJoueur->getSocket(), SIGNAL(readyRead()), this, SLOT(donneesRecues()));
            connect(nouveauJoueur->getSocket(), SIGNAL(disconnected()), this, SLOT(deconnexionClient()));
            if(listJoueurs.size() == NBJOUEUR)
            {
                envoyerA("TOUR",listJoueurs.at(0)->getSocket());
            }
        }else
        {
            Joueur *nouveauJoueur = new Joueur();
            nouveauJoueur->setSocket(serveur->nextPendingConnection());
            QString message = QString::fromUtf8("Nombre de joueurs max atteint!");
            QByteArray paquet;
            QDataStream out(&paquet, QIODevice::WriteOnly);

            out << (quint16) 0;
            out << message;
            out.device()->seek(0);
            out << (quint16) (paquet.size() - sizeof(quint16));

            if(nouveauJoueur->getSocket()->write(paquet) == -1)
            {
                ui->Info->append("Erreur envoi: " + message);
            }
            ui->Info->append("Envoye : " + message);
        }
}

void Serveur::deconnexionClient()
{

    QString joueurSupprime;

    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    if (socket == 0)
        return;

    for (int i = 0; i < listJoueurs.size(); i++)
    {
        if(listJoueurs.at(i)->getSocket() == socket)
        {
            joueurSupprime = listJoueurs.at(i)->getPseudo();
            listJoueurs.removeAt(i);
        }
    }
    socket->deleteLater();
    envoyerATousJoueurs("#" + joueurSupprime + "#");

     tourcourrant = 0;

}

void Serveur::donneesRecues()
{
    ui->Info->append(QString::fromUtf8("Nouvelles données"));
    QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
    if (socket == 0)
        return;

    QDataStream in(socket);
    if (tailleMessage == 0)
    {
        if (socket->bytesAvailable() < (int)sizeof(quint16))
             return;
        in >> tailleMessage;
    }
    if (socket->bytesAvailable() < tailleMessage)
        return;
    QString message;
    in >> message;
    ui->Info->append(QString::fromUtf8("Recu: ") + message);

    int pseudoOk = 0;
    int tt = 0;

    if(message[0] == '&')
    {

        for (int i = 0; i < listJoueurs.size(); i++)
        {
            if(listJoueurs.at(i)->getPseudo() == message.mid(1,message.size() -2))
            {
                pseudoOk = 1;

                envoyerA(QString::fromUtf8("<strong>ERREUR :</strong> Pseudo déjà utilisé"), socket);

                for (int i = 0; i < listJoueurs.size(); i++)
                {
                    if(listJoueurs.at(i)->getSocket() == socket)
                    {
                        listJoueurs.removeAt(i);
                    }
                }
                socket->deleteLater();
            }
        }
        if(pseudoOk == 0)
        {            
            envoyerA(QString::fromUtf8("ConnexionValide"), socket);
            this->listJoueurs.last()->setPseudo(message.mid(1,message.size() -2));
                   for(int i = 0; i < listJoueurs.size(); ++i)
                       envoyerATousJoueurs(tr("&") + listJoueurs.at(i)->getPseudo() + tr("&"));
        }
        if(tt == 0 && listJoueurs.size() == NBJOUEUR)
        {
            tt = 1;
            envoyerATousJoueurs("%" + listJoueurs.at(0)->getPseudo() + "%");
        }
    }else if(message.contains("DEP"))
    {       
        envoyerATous(message ,socket);
        tourcourrant = (tourcourrant+1)%NBJOUEUR;
        envoyerA("TOUR",listJoueurs.at(tourcourrant)->getSocket());
        envoyerATousJoueurs("%" + listJoueurs.at(tourcourrant)->getPseudo() + "%");
    }
    else
        envoyerATousJoueurs(message);

    tailleMessage = 0;
    if (socket->bytesAvailable() > 0)
         donneesRecues();
    socket->flush();
}


void Serveur:: envoyerATous(const QString &message, QTcpSocket *socket)
{
    QByteArray paquet;
    QDataStream out(&paquet, QIODevice::WriteOnly);
    out << (quint16) 0;
    out << message;
    out.device()->seek(0);
    out << (quint16) (paquet.size() - sizeof(quint16));
    for (int i = 0; i < listJoueurs.size(); i++)
    {
        if(listJoueurs.at(i)->getSocket() != socket)
        {
            if(listJoueurs.at(i)->getSocket()->write(paquet) == -1)
            {
                ui->Info->append("Erreur envoi: " + message);
            }
        }
    }
}

void Serveur::envoyerATousJoueurs(const QString &message)
{
    QByteArray paquet;
    QDataStream out(&paquet, QIODevice::WriteOnly);

    out << (quint16) 0;
    out << message;
    out.device()->seek(0);
    out << (quint16) (paquet.size() - sizeof(quint16));
    for (int i = 0; i < listJoueurs.size(); i++)
    {
        if(listJoueurs.at(i)->getSocket()->write(paquet) == -1)
        {
            ui->Info->append("Erreur envoi: " + message);
        }
        ui->Info->append("Envoye : " + message);
    }

}

void Serveur::envoyerA(const QString &message, QTcpSocket *socket){

    QByteArray paquet;
    QDataStream out(&paquet, QIODevice::WriteOnly);
    out << (quint16) 0;
    out << message;
    out.device()->seek(0);
    out << (quint16) (paquet.size() - sizeof(quint16));
    if(socket->write(paquet) == -1)
    {
          ui->Info->append("Erreur envoi: " + message);
     }
    ui->Info->append("Envoye : " + message);

}

void Serveur::on_boutonQuitter_clicked()
{
    exit(1);
}
